// ****************************************************************************
// @File: SmartPtrManager.h
//
// PURPOSE: A manager to hold all the SmartPtrs. ie, it contains the root
//          of the GC.
// AUTHOR:  Zj Ai
//
// NOTES: 
//     
// HISTORY:
//
//   ------ Zj Ai  05/07/2012 creating the file
//
// @EndHeader@
// ****************************************************************************
#pragma once
#include "stdafx.h"
#include "LinkNode.h"
#include "SmartPtr.h"
#include <list>

using namespace std;

class CSmartPtrManager
{
public:
	static CSmartPtrManager* GetInstance();
	// this function will be called only for UT or the end of the process
	// for it will never delete the CSmartPtr
	static void Destroy();

	// return true if need to GC generation 0, bInsertSuccess will be false only insert NULL
	// refuse to add the already inserted pSmartPtr
	bool AddToManager(LinkNode* pSmartPtr, bool &bInsertSuccess);
	void RemveFromManager(LinkNode* pSmartPtr, bool &bRemoveSuccess);

public:
	// the followings used by GC thread
	void CollectNeedGcPtrs(int generation, list<LinkNode*>& listToReceive);
	// shift ptrs survived from last GC, like g0 ptr to g1, and g1 to g2
	// the user does not need to delete the remainPtrs, it will be deleted by GC
	// the return value is whether need another GC, and if -1, no need, if not
	// generation to GC
	int ShiftGcSurvivePtrs(
		int collectedGeneration, /*the last GC collected generation*/
		const list<LinkNode*>& remainPtrs /*remain ptrs after this time's GC*/
		);	

	UINT GetGenerationObjectsCount(int generation);
	ULONG GetGenerationObjectsSize(int generation);

	bool IsEmbeddedPtr(LinkNode *ptr);

	// get and set the status of CSmartPtr
	void SetPtrInUse( LinkNode* ptr, bool bInUse );
	size_t GetSize( LinkNode* ptr );
	bool IsPtrInUse( LinkNode* ptr );
private:
	bool HasEnoughSpaceForGeneration(int generationNum, size_t size);

	CSmartPtrManager();
	~CSmartPtrManager();

private:
	static CSmartPtrManager *m_sSmartPtrManager;

	// the followings are Generations.
	struct GC_Generations
	{
		static UINT thresholdBytes[GENERATIONS_NUM];
		ULONG currentBytes;
		UINT  objectCount;
		list<LinkNode*> smartPtrList;
	}; 
	GC_Generations gc_Generations[GENERATIONS_NUM];

	// to contain all the CSmartPtrs
	list<LinkNode*> allNodesList;
};